package com.alibaba.citrus.cr.mn.order.center.facade.function.convert;

import com.alibaba.citrus.cr.common.enums.ordercenter.DictionaryTypeEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrgTypeEnum;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.mn.order.center.common.SetOrderTag;
import com.alibaba.citrus.cr.mn.order.center.common.util.AssertUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BaseDataServiceAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.CargoZoneAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.LogisticWarehouseQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.SearchScItemQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.BaseDataScItemDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.LogisticWarehouseQueryDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.SalesBizOrgQueryDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.function.dataobject.AtomOrderDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.epoch.app.bcorder.model.dto.WarehouseInfo;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.mnordercenter.model.dto.DictionaryResponse;
import com.epoch.app.mnordercenter.model.dto.ExchangeOrderAtomCreateRequest;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author dongju
 * @ClassName ExchangeOrderParamsConvertService
 * @description: 换货订单入参转换服务
 * @date 2023/05/21
 * @version: 1.0
 */
@Service
public class ExchangeOrderParamsConvertService extends AbstractOrderParamsConvertService<ExchangeOrderAtomCreateRequest, AtomOrderDO> {
    private static final Log log = Log.getLogger(ExchangeOrderParamsConvertService.class);

    @Resource
    private BaseDataServiceAdapter baseDataServiceAdapter;
    @Resource
    private CargoZoneAdapter cargoZoneAdapter;

    @Override
    public List<AtomOrderDO> convert(List<ExchangeOrderAtomCreateRequest> requestList) {
        List<AtomOrderDO> orderDOS = ExchangeOrderAtomCreateRequestToAtomOrderDOConvertor.convert(requestList);

        // 查询货品信息，进行code转id
        List<String> scItemCodes = new ArrayList<>();
        orderDOS.forEach(o -> scItemCodes.addAll(o.getOrderLines().stream().map(OrderLine::getScItemId).distinct().collect(Collectors.toList())));
        Map<String, BaseDataScItemDTO> baseDataScItemMap = queryScItemInfo(scItemCodes);

        // 业务单元Code、组织Code、部门Code、渠道Code
        Map<String, SalesBizOrgQueryDTO> organizationByCodes = findSalesOrgByAtomOrderDO(orderDOS);
        Map<String, String> organizationIdByCodes = Maps.newHashMap();
        organizationByCodes.forEach((code, dto)-> organizationIdByCodes.put(code, String.valueOf(dto.getId())));

        // 从字典服务里获取业态列表
        List<DictionaryResponse> businessTypeResponseList =
                baseDataServiceAdapter.queryDictionarys(DictionaryTypeEnum.BUSINESS_TYPE.getCode());
        Map<String, DictionaryResponse> businessTypeMap = businessTypeResponseList.stream()
                .collect(Collectors.toMap(DictionaryResponse::getCode, Function.identity(), (k1, k2) -> k2));

        Map<String, WarehouseInfo> cacheWarehouseMap = Maps.newHashMap();
        for (AtomOrderDO orderDO : orderDOS) {
            String orgBisUnitCodeId = organizationIdByCodes.get(orderDO.getOrder().getBisUnitCode());
            String orgOrganizationCodeId = organizationIdByCodes.get(SalesOrgTypeEnum.SALES_ORG.getCode() + "_" + orderDO.getOrder().getOrganizationCode());
            String orgDepartmentCodeId = organizationIdByCodes.get(orderDO.getOrder().getDepartmentCode());
            String orgSaleChannelCodeId = organizationIdByCodes.get(orderDO.getOrder().getSaleChannelCode());

            // 当前明细逻辑仓 为同一个
            WarehouseInfo warehouse = queryLgWarehouseInfo(orderDO.getOrderLines().get(0).getShippingWarehouseCode(),
                    orderDO.getOrderLines().get(0).getDeliveryFactoryCode(),
                    orderDO.getOrderLines().get(0).getStockCode(),
                    cacheWarehouseMap);
            // 主单 逻辑仓转换Code->ID
            orderDO.getOrder().setWareHouseCode(warehouse.getId());
            orderDO.getOrder().setWareHouseName(warehouse.getName());
            orderDO.getOrder().setWareHouseOutCode(warehouse.getCode());
            // 查询收货仓库信息
            WarehouseInfo receiveWarehouse = queryLgWarehouseInfo(orderDO.getOrderLines().get(0).getReceiveWarehouseCode(),
                    orderDO.getOrderLines().get(0).getReceiveFactoryCode(),
                    orderDO.getOrderLines().get(0).getReceiveStockCode(),
                    cacheWarehouseMap);
            // 主单 逻辑仓转换Code->ID
            orderDO.getOrder().setReceiveWareHouseCode(receiveWarehouse.getId());
            orderDO.getOrder().setReceiveWareHouseName(receiveWarehouse.getName());
            orderDO.getOrder().setReceiveWareHouseOutCode(receiveWarehouse.getCode());
            // 主单+明细的逻辑仓信息校验 仓库-工厂-库存地点 校验
            checkOrderLineWarehouseInfo(orderDO, warehouse, receiveWarehouse);

            if (orderDO.getOrder().getBusinessType() != null) {
                orderDO.getOrder().setBusinessTypeName(businessTypeMap.get(orderDO.getOrder().getBusinessType().toString()).getName());
            }
            if (StringUtils.isNotBlank(orderDO.getOrder().getBisUnitCode())) {
                SalesBizOrgQueryDTO organizationSDO = organizationByCodes.get(orderDO.getOrder().getBisUnitCode());
                if (organizationSDO != null) {
                    orderDO.getOrder().setBisUnitName(organizationSDO.getOrgName());
                }
            }
            String features = orderDO.getOrder().getFeatures();
            Map<String, String> featuresMap = JSON.parseObject(features, new TypeReference<Map<String, String>>() {
            });
            featuresMap = Optional.ofNullable(featuresMap).orElse(Maps.newHashMap());
            featuresMap.put("logicWarehouseCode", warehouse.getCode());

            // 新增OutCode
            orderDO.getOrder().setBisUnitOutCode(orderDO.getOrder().getBisUnitCode());
            orderDO.getOrder().setOrganizationOutCode(orderDO.getOrder().getOrganizationCode());
            orderDO.getOrder().setDepartmentOutCode(orderDO.getOrder().getDepartmentCode());
            orderDO.getOrder().setSaleChannelOutCode(orderDO.getOrder().getSaleChannelCode());
            orderDO.getOrder().setChannelOutCode(orderDO.getOrder().getChannelCode());

            // 重设为内部ID，兼容订单共享平台逻辑
            orderDO.getOrder().setBisUnitCode(orgBisUnitCodeId);
            orderDO.getOrder().setOrganizationCode(orgOrganizationCodeId);
            orderDO.getOrder().setDepartmentCode(orgDepartmentCodeId);
            orderDO.getOrder().setSaleChannelCode(orgSaleChannelCodeId);

            orderDO.getOrder().setFeatures(JSON.toJSONString(featuresMap));

            for (OrderLine orderLine : orderDO.getOrderLines()) {
                Map<String, String> lineFeaturesMap = JSON.parseObject(orderLine.getFeatures(), new TypeReference<Map<String, String>>() {
                });
                lineFeaturesMap = Optional.ofNullable(lineFeaturesMap).orElse(Maps.newHashMap());
                lineFeaturesMap.put("productCode", orderLine.getScItemId());
                lineFeaturesMap.put("logicWarehouseCode", warehouse.getCode());
                lineFeaturesMap.put("receiveLogicWarehouseCode", receiveWarehouse.getCode());

                // 新增OutCode
                orderLine.setShippingWarehouseOutCode(warehouse.getCode());
                orderLine.setShippingWarehouseCode(warehouse.getId());
                orderLine.setShippingWarehouseName(warehouse.getName());
                orderLine.setDeliveryFactoryCode(warehouse.getSapFactoryCode());
                orderLine.setStockCode(warehouse.getWarehouseCode());

                orderLine.setReceiveWarehouseOutCode(receiveWarehouse.getCode());
                orderLine.setReceiveWarehouseCode(receiveWarehouse.getId());
                orderLine.setReceiveWarehouseName(receiveWarehouse.getName());
                orderLine.setReceiveFactoryCode(receiveWarehouse.getSapFactoryCode());
                orderLine.setReceiveStockCode(receiveWarehouse.getWarehouseCode());

                orderLine.setReceiveFactoryCode(receiveWarehouse.getSapFactoryCode());
                orderLine.setReceiveStockCode(receiveWarehouse.getWarehouseCode());

                orderLine.setFeatures(JSON.toJSONString(lineFeaturesMap));

                // 货品Code转id
                BaseDataScItemDTO baseDataScItemDTO = baseDataScItemMap.get(orderLine.getScItemId());
                if (Objects.isNull(baseDataScItemDTO)) {
                    throw new FunctionException("OC-01-001-01-16-012", orderLine.getScItemId());
                }
                // 将物料编码转为ID
                orderLine.setScItemId(baseDataScItemDTO.getScItemId());

                if(orderDO.isAutoSubmit()) {
                    if (SetOrderTag.EXCHANGE.equals(orderLine.getOrderLineTag())) {
                        // 清空换货行收货仓信息
                        orderLine.setReceiveWarehouseOutCode(null);
                        orderLine.setReceiveWarehouseCode(null);
                        orderLine.setReceiveWarehouseName(null);
                        orderLine.setReceiveFactoryCode(null);
                        orderLine.setReceiveFactoryName(null);
                        orderLine.setReceiveStockCode(null);
                        orderLine.setReceiveStockName(null);
                    }

                    if (SetOrderTag.RETURN.equals(orderLine.getOrderLineTag())) {
                        // 清空退货行发货仓信息
                        orderLine.setShippingWarehouseOutCode(null);
                        orderLine.setShippingWarehouseCode(null);
                        orderLine.setShippingWarehouseName(null);
                        orderLine.setDeliveryFactoryCode(null);
                        orderLine.setDeliveryFactoryName(null);
                        orderLine.setStockCode(null);
                        orderLine.setStockName(null);
                    }
                }
            }
        }
        return orderDOS;
    }

    public WarehouseInfo queryLgWarehouseInfo(String warehouseCode, String factoryCode, String stockCode, Map<String, WarehouseInfo> cacheWarehouseMap) {
        if (StringUtils.isBlank(warehouseCode)) {

            // 查看是否已经缓存 工厂+库存地点
            String key = String.format("%s_%s", factoryCode, stockCode);
            WarehouseInfo warehouseInfo = cacheWarehouseMap.get(key);
            if (Objects.nonNull(warehouseInfo)) {
                return warehouseInfo;
            }
            List<LogisticWarehouseQueryRequest> logisticWarehouseQueryRequests = Lists.newArrayList();
            LogisticWarehouseQueryRequest queryRequest = new LogisticWarehouseQueryRequest();
            queryRequest.setFactoryCode(factoryCode);
            queryRequest.setStorageLocation(stockCode);
            logisticWarehouseQueryRequests.add(queryRequest);
            List<LogisticWarehouseQueryDTO> listResult = cargoZoneAdapter.queryCargoZoneListByParam(logisticWarehouseQueryRequests);

            if (CollectionUtils.isEmpty(listResult)) {
                throw new FunctionException("OC-01-001-01-16-009", String.format("工厂编码:%s, 库存地点编码:%s", factoryCode, stockCode));
            }
            LogisticWarehouseQueryDTO queryWarehouseInfo = listResult.get(0);
            warehouseInfo = new WarehouseInfo();
            warehouseInfo.setId(queryWarehouseInfo.getId());
            warehouseInfo.setWarehouseId(queryWarehouseInfo.getWarehouseId());
            warehouseInfo.setCode(queryWarehouseInfo.getCode());
            warehouseInfo.setName(queryWarehouseInfo.getName());
            warehouseInfo.setWarehouseCode(queryWarehouseInfo.getWarehouseCode());
            warehouseInfo.setSapFactoryCode(queryWarehouseInfo.getSapFactoryCode());

            // (缓存)交货工厂编码+交货库存地点 填充
            cacheWarehouseMap.put(key, warehouseInfo);
            return warehouseInfo;
        }

        // 查看是否已经缓存 逻辑仓库
        WarehouseInfo warehouseInfo = cacheWarehouseMap.get(warehouseCode);
        if (Objects.nonNull(warehouseInfo)) {
            return warehouseInfo;
        }

        // 若 逻辑仓已传，需要通过Code转换ID处理
        LogisticWarehouseQueryRequest queryRequest = new LogisticWarehouseQueryRequest();
        queryRequest.setLogicWarehouseCode(warehouseCode);
        List<LogisticWarehouseQueryRequest> logisticWarehouseQueryRequests = Lists.newArrayList(queryRequest);
        List<LogisticWarehouseQueryDTO> listResult = cargoZoneAdapter.queryCargoZoneListByParam(logisticWarehouseQueryRequests);

        if (CollectionUtils.isNotEmpty(listResult)) {
            LogisticWarehouseQueryDTO queryWarehouseInfo = listResult.get(0);

            warehouseInfo = new WarehouseInfo();
            warehouseInfo.setId(queryWarehouseInfo.getId());
            warehouseInfo.setWarehouseId(queryWarehouseInfo.getWarehouseId());
            warehouseInfo.setCode(queryWarehouseInfo.getCode());
            warehouseInfo.setName(queryWarehouseInfo.getName());
            warehouseInfo.setWarehouseCode(queryWarehouseInfo.getWarehouseCode());
            warehouseInfo.setSapFactoryCode(queryWarehouseInfo.getSapFactoryCode());
            // (缓存) 逻辑仓库
            cacheWarehouseMap.put(warehouseCode, warehouseInfo);
            return warehouseInfo;
        }
        throw new FunctionException("OC-01-001-01-16-009", String.format("逻辑仓编码:%s", warehouseCode));
    }

    private void checkOrderLineWarehouseInfo(AtomOrderDO orderDO, WarehouseInfo shipWarehouse, WarehouseInfo receiveWarehouse) {
        for (OrderLine orderLine : orderDO.getOrderLines()) {
            String shippingWarehouseCode = orderLine.getShippingWarehouseCode();
            String deliveryFactoryCode = orderLine.getDeliveryFactoryCode();
            String stockCode = orderLine.getStockCode();

            if(StringUtils.isNotBlank(shippingWarehouseCode)) {
                String warehouseCode = shipWarehouse.getCode();
                boolean equals = StringUtils.equals(shippingWarehouseCode, warehouseCode);
                AssertUtils.isTrue(!equals, "OC-01-001-01-15-003",
                        orderDO.getSourceOrderNo(), String.format("发货仓库编码：%s", shippingWarehouseCode));
            }
            if(StringUtils.isNotBlank(deliveryFactoryCode)) {
                String sapFactoryCode = shipWarehouse.getSapFactoryCode();
                boolean equals = StringUtils.equals(deliveryFactoryCode, sapFactoryCode);
                AssertUtils.isTrue(!equals, "OC-01-001-01-15-003",
                        orderDO.getSourceOrderNo(), String.format("发货仓库存工厂编码:%s，库存地点编码:%s", deliveryFactoryCode, stockCode));
            }
            if(StringUtils.isNotBlank(stockCode)) {
                String warehouseCode = shipWarehouse.getWarehouseCode();
                boolean equals = StringUtils.equals(stockCode, warehouseCode);
                AssertUtils.isTrue(!equals, "OC-01-001-01-15-003",
                        orderDO.getSourceOrderNo(), String.format("发货仓库存工厂编码:%s，库存地点编码:%s", deliveryFactoryCode, stockCode));
            }

            String receiveWarehouseCode = orderLine.getReceiveWarehouseCode();
            String receiveFactoryCode = orderLine.getReceiveFactoryCode();
            String receiveStockCode = orderLine.getReceiveStockCode();

            if(StringUtils.isNotBlank(receiveWarehouseCode)) {
                String warehouseCode = receiveWarehouse.getCode();
                boolean equals = StringUtils.equals(receiveWarehouseCode, warehouseCode);
                AssertUtils.isTrue(!equals, "OC-01-001-01-15-003",
                        orderDO.getSourceOrderNo(), String.format("收货仓库编码：%s", receiveWarehouseCode));
            }
            if(StringUtils.isNotBlank(receiveFactoryCode)) {
                String sapFactoryCode = receiveWarehouse.getSapFactoryCode();
                boolean equals = StringUtils.equals(receiveFactoryCode, sapFactoryCode);
                AssertUtils.isTrue(!equals, "OC-01-001-01-15-003",
                        orderDO.getSourceOrderNo(), String.format("收货仓库存工厂编码:%s，库存地点编码:%s", deliveryFactoryCode, stockCode));
            }
            if(StringUtils.isNotBlank(receiveStockCode)) {
                String warehouseCode = receiveWarehouse.getWarehouseCode();
                boolean equals = StringUtils.equals(receiveStockCode, warehouseCode);
                AssertUtils.isTrue(!equals, "OC-01-001-01-15-003",
                        orderDO.getSourceOrderNo(), String.format("收货仓库存工厂编码:%s，库存地点编码:%s", deliveryFactoryCode, stockCode));
            }
        }
    }

    private Map<String, BaseDataScItemDTO> queryScItemInfo(List<String> scItemCodes) {
        if (CollectionUtils.isEmpty(scItemCodes)) {
            return Maps.newHashMap();
        }
        SearchScItemQueryRequest request = new SearchScItemQueryRequest();
        request.setPageNum(1);
        request.setPageSize(scItemCodes.size());

        Map<String, Object> searchReqDTO = Maps.newHashMap();
        searchReqDTO.put("outerIdList", scItemCodes);
        request.setSearchReqDTO(searchReqDTO);
        List<BaseDataScItemDTO> scItemDTOS = baseDataServiceAdapter.searchScItemByDBWhenDegraded(request);

        return Optional.ofNullable(scItemDTOS).orElse(Lists.newArrayList())
                .stream()
                .collect(Collectors.toMap(BaseDataScItemDTO::getOuterId, p -> p, (v1, v2) -> v1));
    }
}
